/*
 * date: 2009-11-20 
 * author: Maciej Smolenski <jezdnia@gmail.com>
 */
#ifndef _RPC_DATA_HPP_ 
#define _RPC_DATA_HPP_

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/set.hpp>
#include <boost/interprocess/offset_ptr.hpp>

#include <string>
#include <set>

#include "rpc_common_data.hpp"

namespace rpc_monitor
{

namespace bi = boost::interprocess;

template <typename AT>
struct rpc_service{
	AT address;
	long unsigned program;
	long unsigned version;
	long unsigned port;
	protocol_t protocol;
	state_t state;

	rpc_service(const AT p_address, const long unsigned p_program, const long unsigned p_version, const long unsigned p_port, const protocol_t p_protocol, const state_t p_state); 
	rpc_service(const rpc_service<AT> &r); 
	bool operator<(const rpc_service<AT> &rs) const;
};

template <typename AT>
rpc_service<AT>::rpc_service(const AT p_address, const long unsigned p_program, const long unsigned p_version, const long unsigned p_port, const protocol_t p_protocol, const state_t p_state) : address(p_address), program(p_program), version(p_version), port(p_port), protocol(p_protocol), state(p_state) {};

template <typename AT>
rpc_service<AT>::rpc_service(const rpc_service<AT> &r) : address(r.address), program(r.program), version(r.version), port(r.port), protocol(r.protocol), state(r.state) {};

template <typename AT>
bool rpc_service<AT>::operator<(const rpc_service<AT> &rs) const {
	if (address.compare(rs.address)<0) return true;
	else if (program<rs.program) return true;
	else if (version<rs.version) return true;
	else if (port<rs.port) return true;
	else if (protocol<rs.protocol) return true;
	else if (state<rs.state) return true;
	else return false;
};


struct rpc_service_string;
struct rpc_service_shm_string;

struct rpc_service_string : public rpc_service<std::string>
{
	rpc_service_string(const std::string p_address, const long unsigned p_program, const long unsigned p_version, const long unsigned p_port, const protocol_t p_protocol, const state_t p_state); 
	rpc_service_string(const rpc_service_shm_string &rs);
};

struct rpc_service_shm_string : public rpc_service<shm_string>
{
	rpc_service_shm_string(const shm_string p_address, const long unsigned p_program, const long unsigned p_version, const long unsigned p_port, const protocol_t p_protocol, const state_t p_state); 
	rpc_service_shm_string(const rpc_service_string &rs, shm_char_allocator &al);
};

typedef std::set<rpc_service_string> stdset;
typedef bi::managed_shared_memory::allocator<rpc_service_shm_string>::type shm_rpc_service_shm_string_allocator;
typedef bi::set<rpc_service_shm_string, std::less<rpc_service_shm_string>, shm_rpc_service_shm_string_allocator> biset;

result_t std_set_to_bi_set(bi::managed_shared_memory &segment, const stdset &si, biset &so);
result_t bi_set_to_std_set(bi::managed_shared_memory &segment, const biset &si, stdset &so);

struct rpc_monitor{
	bi::offset_ptr<biset> m_services;	
	result_t init(bi::managed_shared_memory &m_segment);
	result_t deinit(bi::managed_shared_memory &m_segment);
};

std::ostream &operator<<(std::ostream &os, const rpc_service_string &r);

}

#endif
